﻿using CCSSolderUI.Common.Domain;
using CCSSolderUI.Common.Event;
using CCSSolderUI.Models;
using CsvHelper;
using HalconDotNet;
using Newtonsoft.Json;
using NLog;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using ViewROI;

namespace CCSSolderUI.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        #region 变量
        IEventAggregator _eventAggregator;
        private readonly IDialogService dialogService;
        private static Logger logger = LogManager.GetCurrentClassLogger();
        bool isAxisDialogShow = false;
        bool isCameraCalibrationDialogShow = false;
        bool isCameraOperationDialogShow = false;
        bool isJobConfigDialogShow = false;
        bool isMSensorDialogShow = false;
        bool isMScannerDialogShow = false;
        bool isMPLCDialogShow = false;
        bool isMParamDialogShow = false;
        bool isPartNumberDialogShow = false;
        SystemParam systemParam;Param param;
        CancellationTokenSource source1;
        ConcurrentQueue<string> scanerBarQueue = new ConcurrentQueue<string>();
        private bool _stopFlag = false;
        public bool StopFlag
        {
            get { return _stopFlag; }
            set
            {
                if (_stopFlag != value)
                {
                    if (value)
                    {
                        addMessage("急停");
                    }
                    else
                    {
                        addMessage("急停解除");
                    }
                }
                _stopFlag = value;
            }
        }
        private bool _pauseFlag = false;
        public bool PauseFlag
        {
            get { return _pauseFlag; }
            set
            {
                if (_pauseFlag != value)
                {
                    if (value)
                    {
                        addMessage("暂停");
                    }
                    else
                    {
                        addMessage("暂停解除");
                    }
                }
                _pauseFlag = value;
            }
        }
        bool ResetButton = false, PauseButton = false,StartButton1 = false,StartButton2 = false;
        bool SafeDoor1 = false, SafeDoor2 = false, SafeDoor3 = false, SafeDoor4 = false, SafeDoor5 = false, SafeDoor6 = false, SafeDoor7 = false, SafeDoor8 = false, SafeDoor9 = false;
        bool XAlarm = false, YAlarm = false;
        XYZPoint Init_P, ZSafe_P, ZLaser_P, ZLaser_P2, BoardScan1_P, BoardScan2_P, CalibCamera_P;
        CancellationTokenSource source;
        bool X1HomedFlag = false;
        SerialPort xenonSerialPort;
        string Banci="";
        #endregion
        #region 属性绑定
        private string title = "CCS激光焊接机";
        public string Title
        {
            get { return title; }
            set { SetProperty(ref title, value); }
        }
        private string version = "1.2.0";
        public string Version
        {
            get { return version; }
            set { SetProperty(ref version, value); }
        }
        private bool cameraConnectState;
        public bool CameraConnectState
        {
            get { return cameraConnectState; }
            set { SetProperty(ref cameraConnectState, value); }
        }
        private bool axisCardConnectState;
        public bool AxisCardConnectState
        {
            get { return axisCardConnectState; }
            set { SetProperty(ref axisCardConnectState, value); }
        }
        private bool laserConnectState;
        public bool LaserConnectState
        {
            get { return laserConnectState; }
            set { SetProperty(ref laserConnectState, value); }
        }
        private bool scannerConnectState;
        public bool ScannerConnectState
        {
            get { return scannerConnectState; }
            set { SetProperty(ref scannerConnectState, value); }
        }
        private bool pLCConnectState;
        public bool PLCConnectState
        {
            get { return pLCConnectState; }
            set { SetProperty(ref pLCConnectState, value); }
        }
        private string curPartName;
        public string CurPartName
        {
            get { return curPartName; }
            set { SetProperty(ref curPartName, value); }
        }
        private ObservableCollection<DispButton> mainButtonList;
        public ObservableCollection<DispButton> MainButtonList
        {
            get { return mainButtonList; }
            set { SetProperty(ref mainButtonList, value); }
        }
        private string messageStr;
        public string MessageStr
        {
            get { return messageStr; }
            set { SetProperty(ref messageStr, value); }
        }
        private int boardState;
        public int BoardState
        {
            get { return boardState; }
            set { SetProperty(ref boardState, value); }
        }
        private int stepNum;
        public int StepNum
        {
            get { return stepNum; }
            set { SetProperty(ref stepNum, value); }
        }
        private ObservableCollection<string> currentBarcodes = new ObservableCollection<string>();
        public ObservableCollection<string> CurrentBarcodes
        {
            get { return currentBarcodes; }
            set { SetProperty(ref currentBarcodes, value); }
        }
        private ObservableCollection<string> nextBarcodes = new ObservableCollection<string>();
        public ObservableCollection<string> NextBarcodes
        {
            get { return nextBarcodes; }
            set { SetProperty(ref nextBarcodes, value); }
        }
        private string userBarcode;
        public string UserBarcode
        {
            get { return userBarcode; }
            set { SetProperty(ref userBarcode, value); }
        }
        private int curCounter;
        public int CurCounter
        {
            get { return curCounter; }
            set { SetProperty(ref curCounter, value); }
        }
        private long totalCounter;
        public long TotalCounter
        {
            get { return totalCounter; }
            set { SetProperty(ref totalCounter, value); }
        }
        private double cycleTime;
        public double CycleTime
        {
            get { return cycleTime; }
            set { SetProperty(ref cycleTime, value); }
        }
        #region halcon
        private HImage cameraIamge0;
        public HImage CameraIamge0
        {
            get { return cameraIamge0; }
            set { SetProperty(ref cameraIamge0, value); }
        }
        private bool cameraRepaint0;
        public bool CameraRepaint0
        {
            get { return cameraRepaint0; }
            set { SetProperty(ref cameraRepaint0, value); }
        }
        private ObservableCollection<ROI> cameraROIList0 = new ObservableCollection<ROI>();
        public ObservableCollection<ROI> CameraROIList0
        {
            get { return cameraROIList0; }
            set { SetProperty(ref cameraROIList0, value); }
        }
        private HObject cameraAppendHObject0;
        public HObject CameraAppendHObject0
        {
            get { return cameraAppendHObject0; }
            set { SetProperty(ref cameraAppendHObject0, value); }
        }
        private HMsgEntry cameraAppendHMessage0;
        public HMsgEntry CameraAppendHMessage0
        {
            get { return cameraAppendHMessage0; }
            set { SetProperty(ref cameraAppendHMessage0, value); }
        }
        private Tuple<string, object> cameraGCStyle0;
        public Tuple<string, object> CameraGCStyle0
        {
            get { return cameraGCStyle0; }
            set { SetProperty(ref cameraGCStyle0, value); }
        }
        private bool isStepMode;
        public bool IsStepMode
        {
            get { return isStepMode; }
            set { SetProperty(ref isStepMode, value); }
        }
        #endregion
        #endregion
        #region 方法绑定
        private DelegateCommand appLoadedEventCommand;
        public DelegateCommand AppLoadedEventCommand =>
            appLoadedEventCommand ?? (appLoadedEventCommand = new DelegateCommand(ExecuteAppLoadedEventCommand));
        private DelegateCommand appClosedEventCommand;
        public DelegateCommand AppClosedEventCommand =>
            appClosedEventCommand ?? (appClosedEventCommand = new DelegateCommand(ExecuteAppClosedEventCommand));
        private DelegateCommand<object> menuCommand;
        public DelegateCommand<object> MenuCommand =>
            menuCommand ?? (menuCommand = new DelegateCommand<object>(ExecuteMenuCommand));
        private DelegateCommand testButtonCommand;
        public DelegateCommand TestButtonCommand =>
            testButtonCommand ?? (testButtonCommand = new DelegateCommand(ExecuteTestButtonCommand));
        private DelegateCommand operateUpdateCommand;
        public DelegateCommand OperateUpdateCommand =>
            operateUpdateCommand ?? (operateUpdateCommand = new DelegateCommand(ExecuteOperateUpdateCommand));
        private DelegateCommand stepModeSelectCommand;
        public DelegateCommand StepModeSelectCommand =>
            stepModeSelectCommand ?? (stepModeSelectCommand = new DelegateCommand(ExecuteStepModeSelectCommand));

        void ExecuteStepModeSelectCommand()
        {
            param.IsStepMode = IsStepMode;
            addMessage($"单步:{(IsStepMode ? "打开" : "关闭")}");
            try
            {
                string jsonString = JsonConvert.SerializeObject(param, Formatting.Indented);
                File.WriteAllText(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, CurPartName, "Param.json"), jsonString);

                _eventAggregator.GetEvent<MessagePrintEvent>().Publish(new Common.Event.Message() { Sender = "MainWindowView", Type = "Update", Content = null });
            }
            catch (Exception ex)
            {
                addMessage(ex.Message);
            }
        }
        void ExecuteOperateUpdateCommand()
        {
            if (UserBarcode != null)
            {
                using (var sdb = new SysDBContext())
                {
                    sdb.UserBarcodes.Add(new Common.Domain.UserBarcode()
                    {
                        Barcode = UserBarcode,
                        ModifyDate = DateTime.Now
                    });
                    sdb.SaveChanges();
                }
                MessageBox.Show($"员工号{UserBarcode}更新成功", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show($"员工号不能为空", "信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }
        async void ExecuteAppLoadedEventCommand()
        {
            using (var sdb = new SysDBContext())
            {
                var us = sdb.UserBarcodes.OrderByDescending(p => p.ModifyDate).FirstOrDefault();
                if (us != null)
                {
                    UserBarcode = us.Barcode;
                }
            }
            LoadParam();
            UpdateButtonList(0);
            bool r3 = await Task.Run(() => { return Camera.Instance.OpenCamera(systemParam.CameraName); });
            CameraConnectState = r3;
            if (!r3)
            {
                addMessage("相机打开失败");
                return;
            }
            GTSCard.Instance.Init();
            bool r2 = ServoModbus.Instance.Connect(systemParam.ServoCOM);
            if (!r2)
            {
                addMessage("伺服连接失败");
                return;
            }
            else
            {
                try
                {
                    //设置绝对值轴的坐标
                    double y1abs0 = ServoModbus.Instance.ReadInovance(1) * GTSCard.Instance.Y1.Equiv;
                    double cury1pos = y1abs0 - systemParam.Y1Abs;
                    GTSCard.Instance.SigAxisEncSet(GTSCard.Instance.Y1, cury1pos);
                    GTSCard.Instance.SigAxisPosSet(GTSCard.Instance.Y1, cury1pos);
                    double z1abs0 = ServoModbus.Instance.ReadInovance(2) * GTSCard.Instance.Z1.Equiv;
                    double curz1pos = z1abs0 - systemParam.Z1Abs;
                    GTSCard.Instance.SigAxisEncSet(GTSCard.Instance.Z1, curz1pos);
                    GTSCard.Instance.SigAxisPosSet(GTSCard.Instance.Z1, curz1pos);
                }
                catch (Exception ex)
                {
                    addMessage(ex.Message);
                    return;
                }
            }
            bool r4 = await Task.Run(() => { return PLCModbus.Instance.Connect(systemParam.PLCIp); }); 
            PLCConnectState = r4;
            if (!r4)
            {
                addMessage("PLC连接失败");
                return;
            }
            else
            {
                PLCModbus.Instance.WriteSingleRegister(51, systemParam.ScannerState);
                PLCModbus.Instance.WriteMCoil(253, param.IsScanBarcode);
                PLCModbus.Instance.WriteMCoil(250, false);
                PLCModbus.Instance.WriteMCoil(251, false);
                PLCModbus.Instance.WriteMCoil(252, false);
            }
            switch (systemParam.ScannerState)
            {
                case 1:
                    try
                    {
                        this.xenonSerialPort.PortName = systemParam.MannulScannerCOM;
                        this.xenonSerialPort.Open();
                        this.xenonSerialPort.DiscardInBuffer();
                        this.xenonSerialPort.DiscardOutBuffer();
                        this.xenonSerialPort.WriteTimeout = 5000;
                        this.xenonSerialPort.ReadTimeout = 5000;
                        ScannerConnectState = true;
                    }
                    catch (Exception ex)
                    {
                        addMessage(ex.Message);
                        return;
                    }
                    break;
                default:
                    ScannerConnectState = true;
                    break;
            }
            bool r5 = LazerScript("Connect") == "Ok";
            if (r5)
            {
                LazerScript(param.EZDFile);
            }
            string sn = LazerStatus("RSN\r");
            if (sn != null)
            {
                sn = sn.Replace("\r", string.Empty);
                addMessage(sn);
            }
            else
            {
                sn = "";
            }
            bool r6 = sn.Contains("RSN");
            LaserConnectState = r5 && r6;
            if (!r5)
            {
                addMessage("激光器脚本连接失败");
                return;
            }
            if (!r6)
            {
                addMessage("激光器连接失败");
                return;
            }
            try
            {
                DirectoryInfo dir = new DirectoryInfo(Path.Combine(param.ImagePath, CurPartName, "Temp"));
                if (dir.Exists)
                {
                    dir.Delete(true);
                }
                Directory.CreateDirectory(Path.Combine(param.ImagePath, CurPartName, "Temp"));
            }
            catch (Exception ex)
            {
                addMessage(ex.Message);
            }
            addMessage("软件加载完成");
            source1 = new CancellationTokenSource();
            CancellationToken token1 = source1.Token;
            Task.Run(() => Run(token1), token1);
        }
        async void ExecuteAppClosedEventCommand()
        {
            if (source != null)
            {
                source.Cancel();
            }
            if (source1 != null)
            {
                source1.Cancel();
            }
            ResetAction();
            Camera.Instance.CloseCamera();
            ServoModbus.Instance.Close();
            await Task.Delay(300);
            PLCModbus.Instance.Close();
        }
        void ExecuteMenuCommand(object obj)
        {
            switch (obj.ToString())
            {
                case "关于":
                    {
                        DialogParameters param = new DialogParameters();
                        param.Add("Title", Title);
                        param.Add("Version", Version);
                        dialogService.ShowDialog("AboutDialog", param, arg => { });
                    }
                    break;
                case "图像处理底板1":
                    if (!isCameraOperationDialogShow)
                    {
                        isCameraOperationDialogShow = true;
                        DialogParameters parameters = new DialogParameters();
                        parameters.Add("PartNumber", systemParam.ProductList[systemParam.Index]);
                        parameters.Add("Hand", 0);
                        parameters.Add("Distance", param.HDist1);
                        parameters.Add("StandZ", ZLaser_P.Z);
                        dialogService.Show("CameraOperationDialog", parameters, arg =>
                        {
                            isCameraOperationDialogShow = false;
                        });
                    }
                    break;
                case "图像处理底板2":
                    if (!isCameraOperationDialogShow)
                    {
                        isCameraOperationDialogShow = true;
                        DialogParameters parameters = new DialogParameters();
                        parameters.Add("PartNumber", systemParam.ProductList[systemParam.Index]);
                        parameters.Add("Hand", 1);
                        parameters.Add("Distance", param.HDist2);
                        parameters.Add("StandZ", ZLaser_P2.Z);
                        dialogService.Show("CameraOperationDialog", parameters, arg =>
                        {
                            isCameraOperationDialogShow = false;
                        });
                    }
                    break;
                case "标定":
                    if (!isCameraCalibrationDialogShow)
                    {
                        dialogService.ShowDialog("PasswordDialog", arg => {
                            if (arg.Result == ButtonResult.Yes)
                            {
                                var password = arg.Parameters.GetValue<string>("Password");
                                if (password == GetPassWord())
                                {
                                    isCameraCalibrationDialogShow = true;
                                    DialogParameters parameters = new DialogParameters();
                                    parameters.Add("PartNumber", systemParam.ProductList[systemParam.Index]);
                                    dialogService.Show("CameraCalibrationDialog", parameters, arg =>
                                    {
                                        isCameraCalibrationDialogShow = false;
                                    });
                                }
                            }
                        });
                    }
                    break;
                case "轴":
                    if (!isAxisDialogShow)
                    {
                        isAxisDialogShow = true;
                        DialogParameters parameters = new DialogParameters();
                        parameters.Add("PartNumber", systemParam.ProductList[systemParam.Index]);
                        dialogService.Show("AxisDialog", parameters, arg =>
                        {
                            isAxisDialogShow = false;
                        });
                    }
                    break;
                case "作业":
                    if (!isJobConfigDialogShow)
                    {
                        isJobConfigDialogShow = true;
                        DialogParameters parameters = new DialogParameters();
                        parameters.Add("PartNumber", systemParam.ProductList[systemParam.Index]);
                        dialogService.Show("JobConfigDialog", parameters, arg =>
                        {
                            isJobConfigDialogShow = false;
                        });
                    }
                    break;
                case "传感器":
                    if (!isMSensorDialogShow)
                    {
                        isMSensorDialogShow = true;
                        DialogParameters parameters = new DialogParameters();
                        parameters.Add("PartNumber", systemParam.ProductList[systemParam.Index]);
                        dialogService.Show("MSensorDialog", parameters, arg =>
                        {
                            isMSensorDialogShow = false;
                        });
                    }
                    break;
                case "扫码枪":
                    if (!isMScannerDialogShow)
                    {
                        isMScannerDialogShow = true;
                        DialogParameters parameters = new DialogParameters();
                        parameters.Add("PartNumber", systemParam.ProductList[systemParam.Index]);
                        dialogService.Show("MScannerDialog", parameters, arg =>
                        {
                            isMScannerDialogShow = false;
                        });
                    }
                    break;
                case "PLC":
                    if (!isMPLCDialogShow)
                    {
                        isMPLCDialogShow = true;
                        dialogService.Show("MPLCDialog", arg =>
                        {
                            isMPLCDialogShow = false;
                        });
                    }
                    break;
                case "参数":
                    if (!isMParamDialogShow)
                    {
                        dialogService.ShowDialog("PasswordDialog", arg => {
                            if (arg.Result == ButtonResult.Yes)
                            {
                                var password = arg.Parameters.GetValue<string>("Password");
                                if (password == GetPassWord())
                                {
                                    isMParamDialogShow = true;
                                    DialogParameters parameters = new DialogParameters();
                                    parameters.Add("PartNumber", systemParam.ProductList[systemParam.Index]);
                                    dialogService.Show("MParamDialog", parameters, arg =>
                                    {
                                        isMParamDialogShow = false;
                                    });
                                }
                            }
                        });
              
                    }
                    break;
                case "料号":
                    if (!isPartNumberDialogShow)
                    {
                        isPartNumberDialogShow = true;
                        dialogService.Show("PartNumberDialog", arg =>
                        {
                            isPartNumberDialogShow = false;
                        });
                    }
                    break;
                default:
                    //dialogService.ShowDialog("PasswordDialog", arg => { });
                    break;
            }
        }
        void ExecuteTestButtonCommand()
        {
            //Task.Run(() => {
            //    System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
            //    {
            //        CurrentBarcodes.Add("123");
            //        CurrentBarcodes.Add("456");
            //    }));
            //    string barcode = string.Join("-", CurrentBarcodes);
            //});
            //var aa = Path.Combine(@"c:\", string.Empty, "123");
        }

        #endregion
        #region 构造函数
        public MainWindowViewModel(DialogService _dialogService, IEventAggregator ea)
        {
            //ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
            _eventAggregator = ea;
            _eventAggregator.GetEvent<MessagePrintEvent>().Subscribe(MessageReceived);
            NlogConfig();
            dialogService = _dialogService;

            MainButtonList = new ObservableCollection<DispButton>();
            MessageStr = "";

            HOperatorSet.ResetObjDb(5000, 5000, 1);
            HOperatorSet.SetSystem("clip_region", "false");
            HOperatorSet.SetSystem("store_empty_region", "true");

            GTSCard.Instance.StateUpdateEvent += Instance_StateUpdateEvent;
            GTSCard.Instance.MessagePrintEvent += Instance_MessagePrintEvent;
            Camera.Instance.MessagePrintEvent += Instance_MessagePrintEvent1;
            ServoModbus.Instance.MessagePrintEvent += Instance_MessagePrintEvent2;
            PLCModbus.Instance.MessagePrintEvent += Instance_MessagePrintEvent3;

            xenonSerialPort = new SerialPort();
            this.xenonSerialPort.BaudRate = 115200;
            this.xenonSerialPort.Parity = Parity.None;
            this.xenonSerialPort.DataBits = 8;
            this.xenonSerialPort.StopBits = StopBits.One;
            this.xenonSerialPort.DataReceived += this.xenonSerialPort_DataReceived;

            Banci = DXH.Ini.DXHIni.ContentReader("System", "Banci", "Null", System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Count.ini"));
            CurCounter = Convert.ToInt32(DXH.Ini.DXHIni.ContentReader("System", "CurCounter", "0", System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Count.ini")));
            TotalCounter = Convert.ToInt32(DXH.Ini.DXHIni.ContentReader("System", "TotalCounter", "0", System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Count.ini")));
            CycleTime = Convert.ToDouble(DXH.Ini.DXHIni.ContentReader("System", "CycleTime", "0", System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Count.ini")));
        }
        #endregion
        #region 功能函数
        private void MessageReceived(Common.Event.Message obj)
        {
            addMessage($"源:{obj.Sender} 类型:{obj.Type} 内容:{obj.Content}");
            switch (obj.Type)
            {
                case "Print":
                    addMessage(obj.Sender + ":" + obj.Content);
                    break;
                case "Select":
                    LoadParam();
                    break;
                case "Update":
                    if (obj.Sender != "MainWindowView")
                    {
                        LoadParam();
                    }
                    break;
                case "Delete":
                    if (obj.Sender == "PartNumberDialog")
                    {
                        try
                        {
                            string jsonString = File.ReadAllText(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "SystemParam.json"));
                            systemParam = JsonConvert.DeserializeObject<SystemParam>(jsonString);
                        }
                        catch { }
                    }
                    break;
                default:
                    break;
            }
        }
        private void Instance_MessagePrintEvent(object sender, string message)
        {
            addMessage("轴卡:" + message);
        }
        private void Instance_MessagePrintEvent1(object sender, string message)
        {
            addMessage("相机:" + message);
        }
        private void Instance_MessagePrintEvent2(object sender, string message)
        {
            addMessage("伺服:" + message);
        }
        private void Instance_MessagePrintEvent3(object sender, string message)
        {
            addMessage("PLC:" + message);
        }
        private void Instance_StateUpdateEvent(object sender, string status)
        {
            AxisCardConnectState = status == "连接";
            addMessage("轴卡:" + status);
        }
        private void addMessage(string str)
        {
            logger.Debug(str);
            Debug.WriteLine(str);
            string[] s = MessageStr.Split('\n');
            if (s.Length > 1000)
            {
                MessageStr = "";
            }
            if (MessageStr != "")
            {
                MessageStr += "\n";
            }
            MessageStr += DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " " + str;
        }
        private void NlogConfig()
        {
            var config = new NLog.Config.LoggingConfiguration();

            // Targets where to log to: File and Console
            var logfile = new NLog.Targets.FileTarget("logfile") { FileName = "${basedir}/logs/${shortdate}.log", Layout = "${longdate}|${level:uppercase=true}|${message}" };
            var logconsole = new NLog.Targets.ConsoleTarget("logconsole");

            // Rules for mapping loggers to targets            
            config.AddRule(NLog.LogLevel.Info, NLog.LogLevel.Fatal, logconsole);
            config.AddRule(NLog.LogLevel.Debug, NLog.LogLevel.Fatal, logfile);

            // Apply config           
            NLog.LogManager.Configuration = config;
        }
        void LoadParam()
        {
            try
            {
                //Json序列化，从文件读取
                string jsonString = File.ReadAllText(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "SystemParam.json"));
                systemParam = JsonConvert.DeserializeObject<SystemParam>(jsonString);
                string partname = systemParam.ProductList[systemParam.Index];
                CurPartName = partname;
                jsonString = File.ReadAllText(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, systemParam.ProductList[systemParam.Index], "Param.json"));
                param = JsonConvert.DeserializeObject<Param>(jsonString);
                using (var db = new DTContext(partname))
                {
                    var point = db.XYZPoints.FirstOrDefault(p => p.Name == "Init");
                    if (point != null)
                    {
                        Init_P = new XYZPoint
                        {
                            X = point.X,
                            Y = point.Y,
                            Z = point.Z
                        };
                    }
                    point = db.XYZPoints.FirstOrDefault(p => p.Name == "ZSafe");
                    if (point != null)
                    {
                        ZSafe_P = new XYZPoint
                        {
                            X = point.X,
                            Y = point.Y,
                            Z = point.Z
                        };
                    }
                    point = db.XYZPoints.FirstOrDefault(p => p.Name == "ZLaser");
                    if (point != null)
                    {
                        ZLaser_P = new XYZPoint
                        {
                            X = point.X,
                            Y = point.Y,
                            Z = point.Z
                        };
                    }
                    point = db.XYZPoints.FirstOrDefault(p => p.Name == "ZLaser2");
                    if (point != null)
                    {
                        ZLaser_P2 = new XYZPoint
                        {
                            X = point.X,
                            Y = point.Y,
                            Z = point.Z
                        };
                    }
                    point = db.XYZPoints.FirstOrDefault(p => p.Name == "BoardScan1");
                    if (point != null)
                    {
                        BoardScan1_P = new XYZPoint
                        {
                            X = point.X,
                            Y = point.Y,
                            Z = point.Z
                        };
                    }
                    point = db.XYZPoints.FirstOrDefault(p => p.Name == "BoardScan2");
                    if (point != null)
                    {
                        BoardScan2_P = new XYZPoint
                        {
                            X = point.X,
                            Y = point.Y,
                            Z = point.Z
                        };
                    }
                    point = db.XYZPoints.FirstOrDefault(p => p.Name == "CalibCamera");
                    if (point != null)
                    {
                        CalibCamera_P = new XYZPoint
                        {
                            X = point.X,
                            Y = point.Y,
                            Z = point.Z
                        };
                    }
                    
                }
                IsStepMode = param.IsStepMode;
                DirectoryInfo dir = new DirectoryInfo(Path.Combine(param.ImagePath, CurPartName));
                if (!dir.Exists)
                {
                    Directory.CreateDirectory(Path.Combine(param.ImagePath, CurPartName));
                }
                dir = new DirectoryInfo(Path.Combine(param.ComparisonPath, CurPartName));
                if (!dir.Exists)
                {
                    Directory.CreateDirectory(Path.Combine(param.ComparisonPath, CurPartName));
                }
                if (LaserConnectState)
                {
                    LazerScript(param.EZDFile);
                }
            }
            catch (Exception ex)
            {
                addMessage(ex.Message);
            }
        }
        void UpdateButtonList(int hand)
        {
            MainButtonList.Clear();
            using (var db = new DTContext(CurPartName))
            {
               var wps = db.WorkPoints.Where(w => w.Hand == hand).ToList();
                for (int i = 0; i < wps.Count; i++)
                {
                    MainButtonList.Add(new DispButton()
                    {
                        Id = wps[i].Id,
                        Width = 40,
                        Height = 40,
                        Select = false,
                        Name = wps[i].Name,
                        Left = (int)(wps[i].X / 1800 * 560),
                        Bottom = (int)(wps[i].Y / 800 * 560)
                    });
                }
            }
        }
        private void xenonSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int bytesToRead = this.xenonSerialPort.BytesToRead;
            byte[] array = new byte[bytesToRead];
            this.xenonSerialPort.Read(array, 0, bytesToRead);
            string result = System.Text.Encoding.UTF8.GetString(array);
            string[] strs = result.Split(new char[] { '\r' });
            addMessage(strs[0]);
            _eventAggregator.GetEvent<MessagePrintEvent>().Publish(new Common.Event.Message() { Sender = "Main", Type = "Barcode", Content = strs[0] });

            if (param.IsBarcodeSyntax)
            {
                using (var sdb = new SysDBContext())
                {
                    var syntax = sdb.BarcodeSyntaxs.FirstOrDefault(s => s.Id == param.BarcodeSyntaxId);
                    if (syntax != null)
                    {
                        if (!strs[0].StartsWith(syntax.Head))
                        {
                            var s1 = sdb.BarcodeSyntaxs.FirstOrDefault(s => s.Head.Contains(strs[0].Substring(0, 3)));
                            if (s1 != null)
                            {
                                if (MessageBox.Show($"\"{s1.PartName}\"包含条码规则\"{s1.Head}\"\n确认切换料号吗？", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
                                {
                                    int index = -1;
                                    for (int i = 0; i < systemParam.ProductList.Count; i++)
                                    {
                                        if (systemParam.ProductList[i] == s1.PartName)
                                        {
                                            index = i;
                                            break;
                                        }
                                    }
                                    if (index != -1)
                                    {
                                        systemParam.Index = index;
                                        string jsonString = JsonConvert.SerializeObject(systemParam, Newtonsoft.Json.Formatting.Indented);
                                        File.WriteAllText(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "SystemParam.json"), jsonString);
                                        _eventAggregator.GetEvent<MessagePrintEvent>().Publish(new Common.Event.Message { Sender = "Main", Type = "Select", Content = s1.PartName });
                                    }
                                    else
                                    {
                                        return;
                                    }
                                }
                                else
                                {
                                    return;
                                }
                            }
                            else
                            {
                                return;
                            }
                        }
                    }
                }
            }
           
          
            if (PLCModbus.Instance.Connected)
            {
                scanerBarQueue.Enqueue(strs[0]);
                var boardstate = PLCModbus.Instance.ReadDRegisters(50, 1)[0];
                switch (boardState)
                {
                    case 0:
                        while (scanerBarQueue.Count > param.BarCodeLength2)
                        {
                            scanerBarQueue.TryDequeue(out var _);
                        }
                        break;
                    case 1:
                        while (scanerBarQueue.Count > param.BarCodeLength1)
                        {
                            scanerBarQueue.TryDequeue(out var _);
                        }
                        break;
                    default:
                        break;
                }
                PLCModbus.Instance.WriteMCoil(252, true);
            }
            System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                NextBarcodes.Clear();
                foreach (var item in scanerBarQueue)
                {
                    NextBarcodes.Add(item.Substring(0));
                }
            }));
        }
        private void ShowAlarm(string content)
        {
            addMessage(content);
            if (PLCModbus.Instance.Connected)
            {
                PLCModbus.Instance.WriteMCoil(300, true);
            }
            Task.Run(() => {
                System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                {
                    DialogParameters param = new DialogParameters();
                    param.Add("Content", content);
                    dialogService.Show("AlarmDialog", param, arg => {
                        if (PLCModbus.Instance.Connected)
                        {
                            PLCModbus.Instance.WriteMCoil(300, false);
                        }
                    });
                }));

            });
        }
        public void addWaterMaker(HObject ho_Image, out HObject ho_ResultImage, HTuple hv_Row, HTuple hv_Column, HTuple hv_FontSize, HTuple hv_StringVal)
        {
            // Local iconic variables 

            HObject ho_ImageDump, ho_ImageOne, ho_Region;

            // Local control variables 

            HTuple hv_Width = null, hv_Height = null, hv_ExpDefaultWinHandle = new HTuple();
            // Initialize local and output iconic variables 
            HOperatorSet.GenEmptyObj(out ho_ResultImage);
            HOperatorSet.GenEmptyObj(out ho_ImageDump);
            HOperatorSet.GenEmptyObj(out ho_ImageOne);
            HOperatorSet.GenEmptyObj(out ho_Region);

            HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
            HOperatorSet.OpenWindow(0, 0, hv_Width, hv_Height, 0, "buffer", "", out hv_ExpDefaultWinHandle);
            HOperatorSet.DispObj(ho_Image, hv_ExpDefaultWinHandle);

            //设置窗口的字体
            HOperatorSet.SetFont(hv_ExpDefaultWinHandle, "Courier New-Bold-" + hv_FontSize);
            //设置字符串的位置
            HOperatorSet.SetTposition(hv_ExpDefaultWinHandle, hv_Row, hv_Column);
            //写字符串
            HOperatorSet.WriteString(hv_ExpDefaultWinHandle, hv_StringVal);
            //截取窗口
            ho_ImageDump.Dispose();
            HOperatorSet.DumpWindowImage(out ho_ImageDump, hv_ExpDefaultWinHandle);
            HOperatorSet.CloseWindow(hv_ExpDefaultWinHandle);
            //访问第一通道
            ho_ImageOne.Dispose();
            HOperatorSet.AccessChannel(ho_ImageDump, out ho_ImageOne, 1);
            //二值化提取字符串区域
            ho_Region.Dispose();
            HOperatorSet.Threshold(ho_ImageOne, out ho_Region, 255, 255);
            //在原始图像上绘制区域
            ho_ResultImage.Dispose();
            HOperatorSet.PaintRegion(ho_Region, ho_Image, out ho_ResultImage, 255, "fill");
            ho_ImageDump.Dispose();
            ho_ImageOne.Dispose();
            ho_Region.Dispose();

            return;
        }
        private HObject CombinateImage(string directory,int hand,string stringVal)
        {
            try
            {
                // Local iconic variables 
                HObject ho_Image, ho_Image3 = null, ho_Image4 = null, ho_Image5 = null, ho_Image6 = null;
                HObject ho_Rectangle = null;
                // Initialize local and output iconic variables 
                HTuple hv_ImageFiles = null;
                HTuple hv_Index = null;
                HOperatorSet.GenEmptyObj(out ho_Image);
                HOperatorSet.GenEmptyObj(out ho_Image3);
                HOperatorSet.GenEmptyObj(out ho_Image4);
                HOperatorSet.GenEmptyObj(out ho_Image5);
                HOperatorSet.GenEmptyObj(out ho_Image6);
                HOperatorSet.GenEmptyObj(out ho_Rectangle);
                ho_Image.Dispose();
                HOperatorSet.GenImageConst(out ho_Image, "byte", 11520, 2880);
                // Get the subdirectories for the specified directory.
                DirectoryInfo dir = new DirectoryInfo(directory);
                // Get the files in the directory and copy them to the new location.
                FileInfo[] files = dir.GetFiles();
                foreach (FileInfo file in files)
                {
                    //Debug.WriteLine(file.FullName);
                    ho_Image3.Dispose();
                    HOperatorSet.ReadImage(out ho_Image3, file.FullName);

                    //string[] strs = file.Name.Split(new char[] { '.'});
                    string imagefileName = Path.GetFileNameWithoutExtension(file.FullName);
                    ho_Image5.Dispose();
                    HOperatorSet.ZoomImageFactor(ho_Image3, out ho_Image5, 0.5, 0.5, "bilinear");
                    HTuple hv_ImageWidth5 = null, hv_ImageHeight5 = null;
                    HOperatorSet.GetImageSize(ho_Image5, out hv_ImageWidth5, out hv_ImageHeight5);
                    ho_Rectangle.Dispose();
                    HOperatorSet.GenRectangle1(out ho_Rectangle, 0, 0, hv_ImageHeight5 - 1, hv_ImageWidth5 - 1);
                    HTuple hv_Rows = null, hv_Columns = null;
                    HOperatorSet.GetRegionPoints(ho_Rectangle, out hv_Rows, out hv_Columns);
                    HTuple hv_Grayval = null;
                    HOperatorSet.GetGrayval(ho_Image5, hv_Rows, hv_Columns, out hv_Grayval);
                    using (var db = new DTContext(CurPartName))
                    {
                        int id = int.Parse(imagefileName.Split(new char[] { '-' })[0]);
                        string name0 = imagefileName.Split(new char[] { '-' })[1];
                        var wpoint = db.WorkPoints.FirstOrDefault(w => w.Hand == hand && w.Id == id);
                        
                        if (wpoint != null)
                        {
                            var avey = db.WorkPoints.Where(w => w.Hand == hand).Average(w => w.Y);
                            var column6 = wpoint.X * (11520 / 2000) - hv_ImageWidth5.I / 2;
                            int row6 = 0;
                            if (wpoint.Y > avey)
                            {
                                row6 = 2880 / 2;
                            }
                            HOperatorSet.SetGrayval(ho_Image, hv_Rows + row6, hv_Columns + (int)column6, hv_Grayval);
                            ho_Image4.Dispose();
                            addWaterMaker(ho_Image, out ho_Image4, row6 + hv_ImageHeight5.I, (int)(wpoint.X * (11520 / 2000)), 100, name0);
                            ho_Image.Dispose();
                            HOperatorSet.CopyImage(ho_Image4, out ho_Image);
                        }
                    }
                }
                ho_Image6.Dispose();
                addWaterMaker(ho_Image, out ho_Image6, 1340, 0, 200, stringVal);
                return ho_Image6;
            }
            catch (Exception ex)
            {
                addMessage(ex.Message);
                return null;
            }
        }
        private string GetPassWord()
        {
            int day = System.DateTime.Now.Day;
            int month = System.DateTime.Now.Month;
            string ss = (day + month).ToString();
            string passwordstr = "";
            for (int i = 0; i < 4 - ss.Length; i++)
            {
                passwordstr += "0";
            }
            passwordstr += ss;
            return passwordstr;
        }
        #endregion
        #region 运行
        private void Run(CancellationToken token1)
        {
            bool resetButton = false;
            bool safeDoor1 = false, safeDoor2 = false, safeDoor3 = false, safeDoor4 = false, safeDoor5 = false, 
                safeDoor6 = false, safeDoor7 = false, safeDoor8 = false, safeDoor9 = false, 
                pauseButton = false;
            bool xAlarm = false,yAlarm = false;
            ushort _BoardState = 0;
            int stepnum = 0;int cycleCount = 0;
            Stopwatch sw = new Stopwatch(); Stopwatch ctsw = new Stopwatch();
            CancellationToken token;
            bool X1HomeFinish = false, Y1HomeFinish = false;
            int hand = 0;double zlazer = 0;
            List<SysAutoWePO> WePoList = new List<SysAutoWePO>();
            Queue<MWorkPoint> keyQueue = new Queue<MWorkPoint>();
            MWorkPoint keyItem = default;
            double finalX = 0, finalY = 0, finalZ = 0,H1 = 0;
            double ipg_power = 0; double dMarkSpeed = 0;double zposition = 0;
            bool imageResult = true;
            int scanBarCount = 0;
            XYZPoint barPoint = default;
            if (!StopFlag)
            {
                addMessage("请按\"复位\"按钮");
                PLCModbus.Instance.WriteMCoil(256, true);
            }
            while (true)
            {
                if (token1.IsCancellationRequested)
                {
                    return;
                }
                try
                {
                    #region IO信号        
                    if (GTSCard.Instance.OpenCardOk)
                    {
                        XAlarm = GTSCard.Instance.GetAxisAlarm(GTSCard.Instance.X1);
                        YAlarm = GTSCard.Instance.GetAxisAlarm(GTSCard.Instance.Y1);
                    }
                    if (PLCModbus.Instance.Connected)
                    {
                        var xs = PLCModbus.Instance.ReadXCoils(0, 16);
                        StartButton1 = xs[0];
                        StartButton2 = xs[1];
                        StopFlag = !xs[4];
                        ResetButton = xs[2];
                        PauseButton = !xs[3];
                        SafeDoor1 = !xs[7]; SafeDoor2 = !xs[8]; SafeDoor3 = !xs[9]; SafeDoor4 = !xs[10];
                        SafeDoor5 = !xs[11]; SafeDoor6 = !xs[12]; SafeDoor7 = !xs[13]; SafeDoor8 = !xs[14]; SafeDoor9 = !xs[15];
                        double zpos = GTSCard.Instance.GetEnc(GTSCard.Instance.Z1);
                        PLCModbus.Instance.WriteMCoil(255, zpos >= ZSafe_P.Z - 1);
                    }
                    if (SafeDoor1 || SafeDoor2 || SafeDoor3 || SafeDoor4 || SafeDoor5 || SafeDoor6 || SafeDoor7 || SafeDoor8 || SafeDoor9 || PauseButton || XAlarm || YAlarm)
                    {
                        PauseFlag = true;
                    }
                    else
                    {
                        if (PauseFlag)
                        {
                            if (ResetButton)
                            {
                                PauseFlag = false;
                            }
                        }
                    }
                    if (xAlarm != XAlarm)
                    {
                        if (XAlarm)
                        {
                            addMessage("X轴报警");
                        }
                        xAlarm = XAlarm;
                    }
                    if (yAlarm != YAlarm)
                    {
                        if (YAlarm)
                        {
                            addMessage("Y轴报警");
                        }
                        yAlarm = YAlarm;
                    }
                    if (safeDoor1 != SafeDoor1)
                    {
                        if (SafeDoor1)
                        {
                            addMessage("安全门1打开");
                        }
                        safeDoor1 = SafeDoor1;
                    }
                    if (safeDoor2 != SafeDoor2)
                    {
                        if (SafeDoor2)
                        {
                            addMessage("安全门2打开");
                        }
                        safeDoor2 = SafeDoor2;
                    }
                    if (safeDoor3 != SafeDoor3)
                    {
                        if (SafeDoor3)
                        {
                            addMessage("安全门3打开");
                        }
                        safeDoor3 = SafeDoor3;
                    }
                    if (safeDoor4 != SafeDoor4)
                    {
                        if (SafeDoor4)
                        {
                            addMessage("安全门4打开");
                        }
                        safeDoor4 = SafeDoor4;
                    }
                    if (safeDoor5 != SafeDoor5)
                    {
                        if (SafeDoor5)
                        {
                            addMessage("安全门5打开");
                        }
                        safeDoor5 = SafeDoor5;
                    }
                    if (safeDoor6 != SafeDoor6)
                    {
                        if (SafeDoor6)
                        {
                            addMessage("安全门6打开");
                        }
                        safeDoor6 = SafeDoor6;
                    }
                    if (safeDoor7 != SafeDoor7)
                    {
                        if (SafeDoor7)
                        {
                            addMessage("安全门7打开");
                        }
                        safeDoor7 = SafeDoor7;
                    }
                    if (safeDoor8 != SafeDoor8)
                    {
                        if (SafeDoor8)
                        {
                            addMessage("安全门8打开");
                        }
                        safeDoor8 = SafeDoor8;
                    }
                    if (safeDoor9 != SafeDoor9)
                    {
                        if (SafeDoor9)
                        {
                            addMessage("安全门9打开");
                        }
                        safeDoor9 = SafeDoor9;
                    }
                    if (pauseButton != PauseButton)
                    {
                        if (PauseButton)
                        {
                            addMessage("停止按钮按下");
                        }
                        pauseButton = PauseButton;
                    }
                    #endregion
                    #region 外循环
                    if (StopFlag && stepnum >= 0)
                    {
                        if (source != null)
                        {
                            source.Cancel();
                        }
                        ResetAction();
                        stepnum = -2;
                    }
                    #endregion
                    #region 流程
                    switch (stepnum)
                    {
                        case -2:
                            if (!StopFlag)
                            {
                                addMessage("请按\"复位\"按钮");
                                PLCModbus.Instance.WriteMCoil(256, true);
                                stepnum = 0;
                            }
                            break;
                        case 0:
                            if (resetButton != ResetButton)
                            {
                                if (ResetButton)
                                {
                                    bool selfTest = false;
                                    if (AxisCardConnectState)
                                    {
                                        selfTest = true;
                                    }
                                    else
                                    {
                                        if (!AxisCardConnectState)
                                        {
                                            addMessage("轴卡连接失败");
                                        }
                                    }
                                    if (!PauseFlag && selfTest)
                                    {
                                        stepnum = 1;
                                    }
                                }
                                resetButton = ResetButton;
                            }
                            break;
                        case 1:
                            if (!PauseFlag)
                            {
                                //励磁松刹车
                                GTSCard.Instance.ServoOn(GTSCard.Instance.X1);
                                GTSCard.Instance.ServoOn(GTSCard.Instance.Y1);
                                GTSCard.Instance.ServoOn(GTSCard.Instance.Z1);
                                sw.Restart();
                                stepnum = 2;
                            }
                            break;
                        case 2:
                            if (!PauseFlag)
                            {
                                if (sw.Elapsed.TotalSeconds > 2)
                                {
                                    sw.Stop();
                                    //把编码器值复制到规划值
                                    GTSCard.Instance.SigAxisPosSet(GTSCard.Instance.X1, GTSCard.Instance.GetEnc(GTSCard.Instance.X1));
                                    GTSCard.Instance.SigAxisPosSet(GTSCard.Instance.Y1, GTSCard.Instance.GetEnc(GTSCard.Instance.Y1));
                                    GTSCard.Instance.SigAxisPosSet(GTSCard.Instance.Z1, GTSCard.Instance.GetEnc(GTSCard.Instance.Z1));
                                    stepnum = 3;
                                }
                            }
                            break;
                        case 3://Z轴抬到安全位
                            if (!PauseFlag)
                            {
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.Z1, ZSafe_P.Z, param.Z1RunSpeed);
                                stepnum = 4;
                            }
                            break;
                        case 4:
                            if (!PauseFlag)
                            {
                                if (GTSCard.Instance.AxisCheckDone(GTSCard.Instance.Z1))
                                {
                                    stepnum = 5;
                                }
                            }
                            else
                            {
                                GTSCard.Instance.AxisStop(GTSCard.Instance.Z1, 1);
                                stepnum = 3;
                            }
                            break;
                        case 5://Y轴复位和X轴回原点
                            if (!PauseFlag)
                            {
                                if (source != null)
                                {
                                    source.Dispose();
                                }
                                source = new CancellationTokenSource(); token = source.Token;
                                X1HomeFinish = false;
                                Task.Run(() => X1Home(token), token).ContinueWith(t => X1HomeFinish = true);
                                Y1HomeFinish = false;
                                Task.Run(() => Y1Home(token), token).ContinueWith(t => Y1HomeFinish = true);
                                stepnum = 6;
                            }
                            break;
                        case 6:
                            if (!PauseFlag)
                            {
                                if (X1HomeFinish && Y1HomeFinish)
                                {
                                    addMessage("复位完成");
                                    PLCModbus.Instance.WriteMCoil(256, false);
                                    stepnum = 7;
                                }
                            }
                            break;
                        case 7:
                            if (!PauseFlag)
                            {
                                PLCModbus.Instance.WriteMCoil(251, false);
                                PLCModbus.Instance.WriteMCoil(250, true);
                                addMessage("底板交换");
                                stepnum = 8;
                            }
                            break;
                        case 8:
                            if (!PauseFlag)
                            {
                                if (PLCModbus.Instance.ReadMCoils(251, 1)[0])//底板交换好了
                                {
                                    GTSCard.Instance.SetDo(7, 0);
                                    ctsw.Restart();
                                    WePoList.Clear();
                                    _BoardState = PLCModbus.Instance.ReadDRegisters(50, 1)[0];
                                    switch (_BoardState)
                                    {
                                        case 0:
                                            hand = 0;
                                            zlazer = ZLaser_P.Z;
                                            break;
                                        default:
                                            hand = 1;
                                            zlazer = ZLaser_P2.Z;
                                            break;
                                    }
                                    System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                                    {
                                        UpdateButtonList(hand);
                                    }));

                                    if (param.IsScanBarcode)
                                    {
                                        switch (systemParam.ScannerState)
                                        {
                                            case 1://手持扫码枪
                                                System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                                                {
                                                    CurrentBarcodes.Clear();
                                                    foreach (var item in NextBarcodes)
                                                    {
                                                        CurrentBarcodes.Add(item.Substring(0));
                                                    }
                                                    NextBarcodes.Clear();
                                                }));
                                                stepnum = 30;
                                                break;
                                            default://固定扫码枪
                                                System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                                                {
                                                    CurrentBarcodes.Clear();
                                                    NextBarcodes.Clear();
                                                }));
                                                scanBarCount = 0;
                                                stepnum = 10020;//扫码
                                                break;
                                        }
                                    }
                                    else
                                    {
                                        System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                                        {
                                            CurrentBarcodes.Clear();
                                            NextBarcodes.Clear();
                                        }));
                                        stepnum = 30;//焊
                                    }
                                }
                            }
                            break;

                        case 10020:
                            if (scanBarCount < (hand == 0? param.BarCodeLength1 : param.BarCodeLength2))
                            {
                                using var db = new DTContext(CurPartName);
                                var points = db.BarcodePoints.Where(barp => barp.Hand == hand).OrderBy(barp => barp.PcsOrder);
                                if (points.Any())
                                {
                                    if (points.Count() >= scanBarCount + 1)
                                    {
                                        var p1 = points.ToArray()[scanBarCount];
                                        barPoint = new XYZPoint { 
                                            X = p1.X,
                                            Y = p1.Y,
                                            Z = p1.Z
                                        };
                                        stepnum = 20;
                                    }
                                    else
                                    {
                                        ShowAlarm("条码数据缺失");
                                        stepnum = 22;
                                    }
                                }
                                else
                                {
                                    ShowAlarm("条码数据缺失");
                                    stepnum = 22;
                                }
                            }
                            else
                            {
                                stepnum = 30;
                            }
                            break;


                        case 20://扫码
                            //BoardScanPoint1
                            if (!PauseFlag)
                            {
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.X1, barPoint.X, param.X1RunSpeed);
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.Y1, barPoint.Y, param.Y1RunSpeed);
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.Z1, barPoint.Z, param.Z1RunSpeed);
                                stepnum = 21;
                            }
                            break;
                        case 21:
                            if (!PauseFlag)
                            {
                                if (GTSCard.Instance.AxisCheckDone(GTSCard.Instance.X1) && GTSCard.Instance.AxisCheckDone(GTSCard.Instance.Y1) && GTSCard.Instance.AxisCheckDone(GTSCard.Instance.Z1))
                                {
                                    string scb = SHIJIEScanner.Connect(systemParam.FixedScannerIP, systemParam.FixedScannerPort, "Start", true);
                                    //CurrentBarcode = scb;
                                    if (scb == "Error")
                                    {
                                        SHIJIEScanner.Connect(systemParam.FixedScannerIP, systemParam.FixedScannerPort, "Stop", false);
                                        ShowAlarm("扫码失败");
                                        stepnum = 22;
                                    }
                                    else
                                    {
                                        System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                                        {
                                            CurrentBarcodes.Add(scb.Substring(0));
                                        }));
                                        stepnum = 10020;
                                        scanBarCount++;
                                    }
                                }
                            }
                            else
                            {
                                GTSCard.Instance.AxisStop(GTSCard.Instance.X1, 1);
                                GTSCard.Instance.AxisStop(GTSCard.Instance.Y1, 1);
                                GTSCard.Instance.AxisStop(GTSCard.Instance.Z1, 1);
                                stepnum = 20;
                            }
                            break;
                        case 22:
                            if (!PauseFlag)
                            {
                                if (ResetButton)
                                {
                                    //未完待续。。。
                                    stepnum = 61;
                                }
                            }
                            break;
                        case 30:
                            if (!PauseFlag)
                            {
                                keyQueue.Clear();
                                using (var db = new DTContext(CurPartName))
                                {
                                    var wpoints = db.WorkPoints.Where(p => p.Hand == hand && p.IsUse == true).OrderBy(p => p.PcsOrder).ToList();
                                    if (wpoints.Any())
                                    {
                                        for (int i = 0; i < wpoints.Count; i++)
                                        {
                                            MWorkPoint mwp = default;
                                            mwp.ID = wpoints[i].Id;
                                            mwp.Name = wpoints[i].Name;
                                            mwp.X = wpoints[i].X;
                                            mwp.Y = wpoints[i].Y;
                                            mwp.Z = wpoints[i].Z;
                                            mwp.ST_X = wpoints[i].ST_X;
                                            mwp.ST_Y = wpoints[i].ST_Y;
                                            mwp.ST_H = wpoints[i].ST_H;
                                            mwp.BarIndex = wpoints[i].BarIndex;
                                            keyQueue.Enqueue(mwp);
                                        }

                                    }
                                }
                                imageResult = true;
                                stepnum = 31;
                            }
                            break;
                        case 31:
                            if (keyQueue.Count == 0)
                            {
                                //未完待续。。。
                                stepnum = 60;
                            }
                            else
                            {
                                keyItem = keyQueue.Dequeue();
                                System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                                {
                                    var key1 = MainButtonList.FirstOrDefault(b => b.Id == keyItem.ID);
                                    if (key1 != null)
                                    {
                                        key1.Select = true;
                                    }
                                }));
                                stepnum = 32;
                            }
                            break;
                        case 32://拍照
                            if (!PauseFlag)
                            {
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.X1, keyItem.X, param.X1RunSpeed);
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.Y1, keyItem.Y, param.Y1RunSpeed);
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.Z1, keyItem.Z, param.Z1RunSpeed);
                                stepnum = 33;
                            }
                            break;
                        case 33:
                            if (!PauseFlag)
                            {
                                if (GTSCard.Instance.AxisCheckDone(GTSCard.Instance.X1) && GTSCard.Instance.AxisCheckDone(GTSCard.Instance.Y1) && GTSCard.Instance.AxisCheckDone(GTSCard.Instance.Z1))
                                {

                                    stepnum = 34;
                                    GTSCard.Instance.SetDo(2, 0);
                                    sw.Restart();
                                }
                            }
                            else
                            {
                                GTSCard.Instance.AxisStop(GTSCard.Instance.X1, 1);
                                GTSCard.Instance.AxisStop(GTSCard.Instance.Y1, 1);
                                GTSCard.Instance.AxisStop(GTSCard.Instance.Z1, 1);
                                stepnum = 32;
                            }
                            break;
                        case 34:
                            if (!PauseFlag)
                            {
                                if (sw.Elapsed.TotalSeconds >= 0.2 && (!IsStepMode || (StartButton1 || StartButton2) && IsStepMode))
                                {
                                    CameraIamge0 = Camera.Instance.GrabImage();
                                    //存图片
                                    HOperatorSet.WriteImage(CameraIamge0, "jpeg", 0, Path.Combine(param.ImagePath, CurPartName, "Temp", $"{keyItem.ID}-{keyItem.Name}.jpg"));
                                    GTSCard.Instance.SetDo(2, 1);
                                    sw.Stop();
                                    System.Threading.Thread.Sleep(200);
                                    var aa = InspectAction(CameraIamge0, keyItem, hand);
                                    finalX = 0; finalY = 0; finalZ = 0;
                                    if (aa != null)
                                    {
                                        finalX = aa[0].D;
                                        finalY = aa[1].D;
                                        finalZ = aa[2].D;
                                        H1 = aa[3].D;

                                        if (Math.Abs(finalZ) > param.DeltaZLimit)
                                        {
                                            ShowAlarm($"检测高度超差:{finalZ} > {param.DeltaZLimit}\n按\"启动\"焊接\n按\"复位\"跳过");
                                            stepnum = 46;
                                        }
                                        else
                                        {
                                            stepnum = 40;
                                        }
                                    }
                                    else
                                    {
                                        //ShowAlarm("拍照失败");
                                        //stepnum = 35;
                                        imageResult = false;
                                        System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                                        {
                                            CameraAppendHMessage0 = null;
                                            CameraAppendHMessage0 = new HMsgEntry("NG", 100, 100, "red", "image", null, null, 36, "mono", "true");
                                        }));
                                        stepnum = 31;
                                    }
                                }
                            }
                            break;
                        case 35:
                            if (!PauseFlag)
                            {
                                if (ResetButton)
                                {
                                    stepnum = 31;
                                }
                            }
                            break;
                        case 46:
                            if (!PauseFlag)
                            {

                                if (StartButton1 || StartButton2)
                                {
                                    stepnum = 40;
                                }
                                else if (ResetButton)
                                {
                                    stepnum = 31;
                                }

                            }
                            break;
                        case 40:
                            if (!PauseFlag)
                            {
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.X1, finalX + keyItem.ST_X, param.X1RunSpeed);
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.Y1, finalY + keyItem.ST_Y, param.Y1RunSpeed);
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.Z1, zlazer - finalZ + keyItem.ST_H, param.Z1RunSpeed);
                                stepnum = 41;
                            }
                            break;
                        case 41:
                            if (!PauseFlag)
                            {
                                if (GTSCard.Instance.AxisCheckDone(GTSCard.Instance.X1) && GTSCard.Instance.AxisCheckDone(GTSCard.Instance.Y1) && GTSCard.Instance.AxisCheckDone(GTSCard.Instance.Z1))
                                {
                                    //addMessage($"zlazer - finalZ = {zlazer} - {finalZ} = {zlazer - finalZ}");
                                    //addMessage($"Z = {Math.Round(GTSCard.Instance.GetEnc(GTSCard.Instance.Z1), 3)}");
                                    stepnum = 42;
                                }
                            }
                            else
                            {
                                GTSCard.Instance.AxisStop(GTSCard.Instance.X1, 1);
                                GTSCard.Instance.AxisStop(GTSCard.Instance.Y1, 1);
                                GTSCard.Instance.AxisStop(GTSCard.Instance.Z1, 1);
                                stepnum = 40;
                            }
                            break;
                        case 42:
                            if (!PauseFlag)
                            {

                                if (!IsStepMode || (StartButton1 || StartButton2) && IsStepMode)
                                {
                                    if (param.IsLazer)
                                    {
                                        stepnum = 43;
                                    }
                                    else
                                    {
                                        stepnum = 50;
                                    }
                                }

                            }
                            break;
                        case 43:
                            if (!PauseFlag)
                            {

                                //sw.Restart();
                                bool rflag = true;
                                Task.Run(() =>
                                {
                                    List<double> rlist = new List<double>();
                                    while (rflag)
                                    {
                                        string str = LazerStatus("ROP\r");//ROP: 333
                                        string[] strs = str.Replace("\r", string.Empty).Replace(" ", string.Empty).Split(new char[] { ':' });
                                        try
                                        {
                                            rlist.Add(double.Parse(strs[1]));
                                            ipg_power = rlist.Max();
                                        }
                                        catch { }
                                        System.Threading.Thread.Sleep(50);
                                    }
                                });
                                var str = LazerScript("Start");
                                rflag = false;
                                var strs = str.Split(new char[] { ':' });
                                try
                                {
                                    dMarkSpeed = double.Parse(strs[1]);
                                }
                                catch { }
                                stepnum = 50;
                            }
                            break;
                        //case 44:
                        //    {
                        //        stepnum = 50;
                        //        //else if (sw.Elapsed.TotalSeconds >= 2)
                        //        //{
                        //        //    ShowAlarm("激光超时");
                        //        //    stepnum = 45;
                        //        //}
                        //    }
                        //    break;
                        //case 45:
                        //    if (!PauseFlag)
                        //    {
                        //        if (ResetButton)
                        //        {
                        //            stepnum = 50;
                        //        }
                        //    }
                        //    break;
                        case 50:
                            if (!PauseFlag)
                            {
                                zposition = GTSCard.Instance.GetEnc(GTSCard.Instance.Z1);
                                string bar = string.Empty;
                                if (keyItem.BarIndex < currentBarcodes.Count)
                                {
                                    bar = currentBarcodes[keyItem.BarIndex];
                                }
                                try
                                {
                                    string filename = Path.Combine(param.ComparisonPath, CurPartName, DateTime.Now.ToString("yyyyMMdd") + ".csv");
                                    if (!File.Exists(filename))
                                    {
                                        using (var writer = new StreamWriter(filename))
                                        using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
                                        {
                                            csv.WriteHeader<Comparison>();
                                            csv.NextRecord();
                                        }
                                    }
                                 
                                    using (var stream = File.Open(filename, FileMode.Append))
                                    using (var writer = new StreamWriter(stream))
                                    using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
                                    {
                                     
                                        csv.WriteRecord(new Comparison
                                        {
                                            条码 = bar,
                                            开始时间 = DateTime.Now,
                                            功率 = ipg_power,
                                            速度 = dMarkSpeed,
                                            焦距 = zposition,
                                            测高 = H1,
                                            焊接点 = keyItem.Name
                                        });
                                        csv.NextRecord();
                                    }
                                }
                                catch (Exception ex)
                                {
                                    addMessage(ex.Message);
                                }


                                WePoList.Add(new SysAutoWePO
                                {
                                    //"barCode": "92254801AN5120004",
                                    //"coordinateZ": "-91.631",
                                    //"power": "464",
                                    //"ranging": "67.5",
                                    //"serialNo": "19",
                                    //"speed": "650",
                                    //"time": "20220512150019",
                                    //"wave": "0"
                                    barCode = bar,
                                    coordinateZ = zposition.ToString("F3"),
                                    power = ipg_power.ToString(),
                                    ranging = H1.ToString("F1"),
                                    serialNo = keyItem.Name,
                                    speed = dMarkSpeed.ToString(),
                                    time = DateTime.Now.ToString("yyyyMMddHHmmss"),
                                    wave = 0.ToString()
                                });
                                stepnum = 31;
                            }
                            break;
                        case 60:
                            if (!PauseFlag)
                            {
                                stepnum = 61;
                                //另外再开一个任务，做数据
                                Task.Run(() =>
                                {
                                    string barcode = string.Join("-", CurrentBarcodes);
                                    if (barcode == string.Empty)
                                    {
                                        barcode = DateTime.Now.ToString("yyyyMMddHHmmddss");
                                    }
                                    CombinateAction(hand, barcode, imageResult);
                                }).ContinueWith(t => { addMessage("拼图处理完成"); });
                                if (param.IsMES && param.IsLazer)
                                {
                                    List<SysAutoWePO> wePoList1 = new List<SysAutoWePO>();
                                    foreach (var item in WePoList)
                                    {
                                        wePoList1.Add(new SysAutoWePO
                                        {
                                            barCode = item.barCode,
                                            coordinateZ = item.coordinateZ,
                                            power = item.power,
                                            ranging = item.ranging,
                                            serialNo = item.serialNo,
                                            speed = item.speed,
                                            time = item.time,
                                            wave = item.wave
                                        });
                                    }
                                    Task.Run(() =>
                                    {
                                        MESAciton(wePoList1);
                                    }).ContinueWith(t => { addMessage("MES处理完成"); });
                                }
                            }
                            break;
                        case 61:
                            if (!PauseFlag)
                            {
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.Z1, Init_P.Z, param.Z1RunSpeed);
                                stepnum = 62;
                            }
                            break;
                        case 62:
                            if (!PauseFlag)
                            {
                                if (GTSCard.Instance.AxisCheckDone(GTSCard.Instance.Z1))
                                {
                                    stepnum = 63;
                                }
                            }
                            else
                            {
                                GTSCard.Instance.AxisStop(GTSCard.Instance.Z1, 1);
                                stepnum = 61;
                            }
                            break;
                        case 63:
                            if (!PauseFlag)
                            {
                                //等数据流程走完
                                stepnum = 7;
                                GTSCard.Instance.SetDo(7, 1);
                                CycleTime = Math.Round(ctsw.Elapsed.TotalSeconds, 1);
                                ctsw.Stop();
                                DXH.Ini.DXHIni.WritePrivateProfileString("System", "CycleTime", CycleTime.ToString(), System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Count.ini"));
                                CurCounter++;
                                TotalCounter++;
                                DXH.Ini.DXHIni.WritePrivateProfileString("System", "CurCounter", CurCounter.ToString(), System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Count.ini"));
                                DXH.Ini.DXHIni.WritePrivateProfileString("System", "TotalCounter", TotalCounter.ToString(), System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Count.ini"));
                            }
                            break;
                        default:
                            break;
                    }
                    #endregion
                }
                catch { }
                System.Threading.Thread.Sleep(10);
                if (cycleCount++ > 100)
                {
                    cycleCount = 0;
                    BoardState = _BoardState;
                    StepNum = stepnum;
                    try
                    {
                        var banci = GetBanci();
                        if (banci != Banci)
                        {
                            addMessage("换班数据清零。");

                            string filename = Path.Combine(param.ComparisonPath, "产量统计.csv");
                            if (!File.Exists(filename))
                            {
                                using (var writer = new StreamWriter(filename))
                                using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
                                {
                                    csv.WriteHeader<ProductionStatistic>();
                                    csv.NextRecord();
                                }
                            }
                            using (var stream = File.Open(filename, FileMode.Append))
                            using (var writer = new StreamWriter(stream))
                            using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
                            {
                                csv.WriteRecord(new ProductionStatistic
                                {
                                    Time = DateTime.Now,
                                    CurCount = CurCounter,
                                    TotalCount = TotalCounter
                                });
                                csv.NextRecord();
                            }
                            Banci = banci;
                            CurCounter = 0;
                            DXH.Ini.DXHIni.WritePrivateProfileString("System", "CurCounter", "0", System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Count.ini"));
                            DXH.Ini.DXHIni.WritePrivateProfileString("System", "Banci", Banci, System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Count.ini"));
                        }
                    }
                    catch { }
                }
            }
        }
        private void ResetAction()
        {
            GTSCard.Instance.AxisStop(GTSCard.Instance.X1, 1);
            GTSCard.Instance.AxisStop(GTSCard.Instance.Y1, 1);
            GTSCard.Instance.AxisStop(GTSCard.Instance.Z1, 1);
            GTSCard.Instance.ServoOff(GTSCard.Instance.X1);
            GTSCard.Instance.ServoOff(GTSCard.Instance.Y1);
            GTSCard.Instance.ServoOff(GTSCard.Instance.Z1);
            if (PLCModbus.Instance.Connected)
            {
                PLCModbus.Instance.WriteMCoil(250, false);
                PLCModbus.Instance.WriteMCoil(256, false);
            }
            GTSCard.Instance.SetDo(0, 1);//激光
            GTSCard.Instance.SetDo(1, 1);//Z轴刹车
            GTSCard.Instance.SetDo(2, 1);//光源
            GTSCard.Instance.SetDo(7, 1);

        }
        private void X1Home(CancellationToken token)
        {
            int stepnum = 0;
            addMessage("X轴回原点中");
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }
                try
                {
                    switch (stepnum)
                    {
                        case 0:
                            if (!X1HomedFlag)
                            {
                                stepnum = 3;
                            }
                            else
                            {
                                stepnum = 5;
                            }
                            break;
                        case 3:
                            if (!PauseFlag)
                            {
                                GTSCard.Instance.SigAxisHomeMove(GTSCard.Instance.X1);
                                stepnum = 4;
                            }
                            break;
                        case 4:
                            if (!PauseFlag)
                            {
                                if (GTSCard.Instance.SigAxisHomeCheckDone(GTSCard.Instance.X1))
                                {
                                    System.Threading.Thread.Sleep(1000);
                                    GTSCard.Instance.SigAxisHomeZeroSet(GTSCard.Instance.X1);
                                    X1HomedFlag = true;
                                    stepnum = 5;
                                }
                            }
                            else
                            {
                                GTSCard.Instance.AxisStop(GTSCard.Instance.X1, 1);
                                stepnum = 3;
                            }
                            break;
                        case 5:
                            if (!PauseFlag)
                            {
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.X1, Init_P.X, param.X1RunSpeed );
                                stepnum = 6;
                            }
                            break;
                        case 6:
                            if (!PauseFlag)
                            {
                                if (GTSCard.Instance.AxisCheckDone(GTSCard.Instance.X1))
                                {
                                    addMessage("X轴回原点完成");
                                    return;
                                }
                            }
                            else
                            {
                                GTSCard.Instance.AxisStop(GTSCard.Instance.X1, 1);
                                stepnum = 5;
                            }
                            break;
                        default:
                            break;
                    }
                }
                catch (Exception ex)
                {

                }
                System.Threading.Thread.Sleep(100);
            }
        }
        private void Y1Home(CancellationToken token)
        {
            int stepnum = 5;
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }
                try
                {
                    switch (stepnum)
                    {
                        case 5:
                            if (!PauseFlag)
                            {
                                GTSCard.Instance.AxisPosMove(ref GTSCard.Instance.Y1, Init_P.Y, param.Y1RunSpeed );
                                stepnum = 6;
                            }
                            break;
                        case 6:
                            if (!PauseFlag)
                            {
                                if (GTSCard.Instance.AxisCheckDone(GTSCard.Instance.Y1))
                                {
                                    return;
                                }
                            }
                            else
                            {
                                GTSCard.Instance.AxisStop(GTSCard.Instance.Y1, 1);
                                stepnum = 5;
                            }
                            break;
                        default:
                            break;
                    }
                }
                catch (Exception ex)
                {

                }
                System.Threading.Thread.Sleep(100);
            }
        }
        private HTuple[] InspectAction(HObject img,MWorkPoint mwp,int Hand)
        {
            try
            {
                // Local iconic variables 

                HObject ho_Image,ho_Region, ho_RegionErosion;
                HObject ModelRegion, ho_ConnectedRegions, ho_SelectedRegions, ho_RegionFillUp;

                // Initialize local and output iconic variables 
                HOperatorSet.GenEmptyObj(out ho_Image);
                HOperatorSet.GenEmptyObj(out ModelRegion);
                HOperatorSet.GenEmptyObj(out ho_RegionErosion);
                HOperatorSet.GenEmptyObj(out ho_ConnectedRegions);
                HOperatorSet.GenEmptyObj(out ho_SelectedRegions);
                HOperatorSet.GenEmptyObj(out ho_RegionFillUp);

                HOperatorSet.ReadRegion(out ModelRegion, System.IO.Path.Combine(System.Environment.CurrentDirectory, CurPartName, "ModelRegion.hobj"));
                HOperatorSet.ReduceDomain(img, ModelRegion, out ho_Image);
                HOperatorSet.Threshold(ho_Image, out ho_Region, 200, 255);
                ho_RegionErosion.Dispose();
                HOperatorSet.ErosionCircle(ho_Region, out ho_RegionErosion, 1);
                ho_ConnectedRegions.Dispose();
                HOperatorSet.Connection(ho_RegionErosion, out ho_ConnectedRegions);
                ho_SelectedRegions.Dispose();
                HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, "area",
                    "and", param.AreaMinThreshold, param.AreaMaxThreshold);
                ho_RegionFillUp.Dispose();
                HOperatorSet.FillUp(ho_SelectedRegions, out ho_RegionFillUp);

                //System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                //{
                
                //}));

                HTuple number;
                HOperatorSet.CountObj(ho_SelectedRegions, out number);
                HTuple area = null, row = null, column = null;
                HTuple row1 = null, column1 = null, phi = null, length1 = null, length2 = null;
                if (number.I > 1)
                {
                    addMessage("找到多个模板");
                    return null;
                }
                else if (number.I == 0)
                {
                    addMessage("未找到模板");
                    return null;
                }
                else
                {
                    HOperatorSet.AreaCenter(ho_SelectedRegions, out area, out row, out column);

                    HOperatorSet.SmallestRectangle2(ho_RegionFillUp, out row1, out column1, out phi, out length1, out length2);
                    HObject rec2;
                    HOperatorSet.GenEmptyObj(out rec2);
                    HOperatorSet.GenRectangle2(out rec2, row1, column1, phi, length1, length2);

                    System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                    {
                        CameraAppendHObject0 = null;
                        CameraGCStyle0 = new Tuple<string, object>("Color", "green");
                        CameraGCStyle0 = new Tuple<string, object>("DrawMode", "margin");
                        CameraAppendHObject0 = rec2;
                        CameraRepaint0 = !CameraRepaint0;
                        CameraAppendHMessage0 = null;
                        CameraAppendHMessage0 = new HMsgEntry($"面积:{area.D}\n坐标:{row1.D:F1},{column1.D:F1}", 100, 100, "black", "image", null, null, 12, "mono", "false");
                    }));
                }
                ho_Image.Dispose();
                ho_Region.Dispose();
                ModelRegion.Dispose();
                ho_RegionErosion.Dispose();
                ho_ConnectedRegions.Dispose();
                ho_SelectedRegions.Dispose();
                ho_RegionFillUp.Dispose();
                HTuple homMat2D;
                HOperatorSet.ReadTuple(System.IO.Path.Combine(System.Environment.CurrentDirectory, "Calib\\MoveCameraCalibHomMat2D.tup"), out homMat2D);
                HTuple x1, y1;
                HOperatorSet.AffineTransPoint2d(homMat2D, row1, column1, out x1, out y1);
                double x2 = x1 + mwp.X - CalibCamera_P.X;//当前位置-标定拍照位+计算出来的位置
                double y2 = y1 + mwp.Y - CalibCamera_P.Y;
                double h1 = 0,h2 = 0;
                switch (Hand)
                {
                    case 0:
                        h2 = h1 = param.HDist1;
                        break;
                    case 1:
                        h2 = h1 = param.HDist2;
                        break;
                    default:
                        break;
                }
                if (PLCModbus.Instance.Connected)
                {
                    var aa = PLCModbus.Instance.ReadDRegisters(100, 1);
                    if (aa != null)
                    {
                        var bb = Convert.ToInt16(aa[0].ToString("X4"), 16);
                        h1 = Math.Round(bb / 20000.0 * 280 - 140 + 300, 1);
                    }
                }

                addMessage($"计算结果:X:{Math.Round(x2, 3)} Y:{Math.Round(y2, 3)} H:{Math.Round(h1, 3)} △H:{Math.Round(h1 - h2, 3)}");
                return new HTuple[4] { Math.Round(x2, 3), Math.Round(y2, 3), Math.Round(h1 - h2, 3), Math.Round(h1, 3) };
            }
            catch (Exception ex)
            {
                addMessage(ex.Message);
                return null;
            }
        }
        private string LazerScript(string cmdstr)
        {
            try
            {
                using (TcpClient client = new TcpClient("127.0.0.1", 13000))
                {
                    // Translate the passed message into ASCII and store it as a Byte array.
                    Byte[] data = System.Text.Encoding.ASCII.GetBytes(cmdstr);

                    // Get a client stream for reading and writing.
                    //  Stream stream = client.GetStream();

                    NetworkStream stream = client.GetStream();

                    // Send the message to the connected TcpServer.
                    stream.Write(data, 0, data.Length);
                    // Buffer to store the response bytes.
                    data = new Byte[256];

                    // String to store the response ASCII representation.
                    string responseData = string.Empty;

                    // Read the first batch of the TcpServer response bytes.
                    int bytes = stream.Read(data, 0, data.Length);
                    responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);                    

                    // Close everything.
                    stream.Close();
                    client.Close();
                    return responseData;
                }
            }
            catch (Exception ex)
            {
                addMessage(ex.Message);
                return null;
            }
        }
        private string LazerStatus(string cmdstr)
        {
            try
            {
                using (TcpClient client = new TcpClient("192.168.3.230", 10001))
                {
                    // Translate the passed message into ASCII and store it as a Byte array.
                    Byte[] data = System.Text.Encoding.ASCII.GetBytes(cmdstr);

                    // Get a client stream for reading and writing.
                    //  Stream stream = client.GetStream();

                    NetworkStream stream = client.GetStream();

                    // Send the message to the connected TcpServer.
                    stream.Write(data, 0, data.Length);
                    // Buffer to store the response bytes.
                    data = new Byte[256];

                    // String to store the response ASCII representation.
                    string responseData = string.Empty;

                    // Read the first batch of the TcpServer response bytes.
                    int bytes = stream.Read(data, 0, data.Length);
                    responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);

                    // Close everything.
                    stream.Close();
                    client.Close();
                    return responseData;
                }
            }
            catch (Exception ex)
            {
                addMessage(ex.Message);
                return null;
            }
        }
        private void CombinateAction(int hand, string barcode, bool result)
        {
            #region 拼图
            try
            {
                string datetimestr = DateTime.Now.ToString("yyyyMMdd");
                string CombinatePath = Path.Combine(param.ImagePath, CurPartName, datetimestr, "Combinate");
                string okPath = Path.Combine(param.ImagePath, CurPartName, datetimestr, "ok");
                string ngPath = Path.Combine(param.ImagePath, CurPartName, datetimestr, "ng");
                string tempPath = Path.Combine(param.ImagePath, CurPartName, Guid.NewGuid().ToString());
                DirectoryInfo dir = new DirectoryInfo(CombinatePath);
                if (!dir.Exists)
                {
                    Directory.CreateDirectory(CombinatePath);
                }
                dir = new DirectoryInfo(okPath);
                if (!dir.Exists)
                {
                    Directory.CreateDirectory(okPath);
                }
                dir = new DirectoryInfo(ngPath);
                if (!dir.Exists)
                {
                    Directory.CreateDirectory(ngPath);
                }

                FileHelper.DirectoryCopy(Path.Combine(param.ImagePath, CurPartName, "Temp"), tempPath, false);
                dir = new DirectoryInfo(Path.Combine(param.ImagePath, CurPartName, "Temp"));
                if (dir.Exists)
                {
                    dir.Delete(true);
                }
                Directory.CreateDirectory(Path.Combine(param.ImagePath, CurPartName, "Temp"));

                string resultImagePath = result ? okPath : ngPath;
                dir = new DirectoryInfo(Path.Combine(resultImagePath, barcode));
                if (!dir.Exists)
                {
                    Directory.CreateDirectory(Path.Combine(resultImagePath, barcode));
                }
                // Get the files in the directory and copy them to the new location.
                DirectoryInfo dirtemp = new DirectoryInfo(tempPath);
                FileInfo[] filestemp = dirtemp.GetFiles();
                foreach (FileInfo file in filestemp)
                {
                    string filename = Path.GetFileNameWithoutExtension(file.FullName).Split(new char[] { '-' })[1] + (result ? "-OK" : "-NG") + Path.GetExtension(file.FullName);
                    string tempPath1 = Path.Combine(resultImagePath, barcode, filename);
                    file.CopyTo(tempPath1, true);
                }

                var image1 = CombinateImage(tempPath, hand, barcode);
                dirtemp.Delete(true);
                if (image1 != null)
                {
                    HOperatorSet.WriteImage(image1, "jpeg", 0, Path.Combine(CombinatePath, $"{barcode}.jpg"));
                }
            }
            catch (Exception ex)
            {
                addMessage(ex.Message);
            }
            
            #endregion
        }
        private void MESAciton(List<SysAutoWePO> wePoList)
        {
            #region MES
            try
            {
                var content = new StringContent(JsonConvert.SerializeObject(wePoList, Formatting.Indented), Encoding.UTF8, "application/json");
                using (HttpClient client = new HttpClient())
                {
                    var result = client.PostAsync(param.MESPath, content).Result;
                    string backstring = result.Content.ReadAsStringAsync().Result;
                    var mr = JsonConvert.DeserializeObject<MESResponse>(backstring);
                    if (mr.status == 100)
                    {
                        //addMessage("MES上传成功");
                    }
                    else
                    {
                        addMessage($"MES上传失败:{backstring}");
                    }
                }
            }
            catch (Exception ex)
            {
                addMessage(ex.Message);
            }
            #endregion
        }
        private string GetBanci()
        {
            string rs = "";
            if (DateTime.Now.Hour >= 8 && DateTime.Now.Hour < 20)
            {
                rs += DateTime.Now.ToString("yyyyMMdd") + "_D";
            }
            else
            {
                if (DateTime.Now.Hour >= 0 && DateTime.Now.Hour < 8)
                {
                    rs += DateTime.Now.AddDays(-1).ToString("yyyyMMdd") + "_N";
                }
                else
                {
                    rs += DateTime.Now.ToString("yyyyMMdd") + "_N";
                }
            }
            return rs;
        }
        #endregion
    }
    class ProductionStatistic
    {
        public DateTime Time { get; set; }
        public int CurCount { get; set; }
        public long TotalCount { get; set; }
    }
    public class DispButton : INotifyPropertyChanged
    {
        public int Id { get; set; }
        public int Left { get; set; }
        public int Bottom { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public string Name { get; set; }
        private bool select;
        public bool Select
        { 
            get { return select; }
            set 
            { 
                select = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("Select"));
                }
            }
        }

        public event PropertyChangedEventHandler? PropertyChanged;
    }
    public struct MWorkPoint
    {
        public int ID;
        public string Name;
        public double X;
        public double Y;
        public double Z;
        public double ST_X;
        public double ST_Y;
        public double ST_H;
        public int BarIndex;
    }
}
